use qjs_sys as q;
use crate::context::{JSContext,JSPropertyItem};
use crate::value::{RawJsValue};
use crate::{JSRuntime};
use ansi_term::Colour::{Red,Yellow};
use std::ffi::{CString};

pub fn init_internal(ctx:&mut JSContext,_rt:&JSRuntime) {
  #[cfg(windows)]
  let _ = ansi_term::enable_ansi_support();
  let propslist = vec!(
      JSPropertyItem::object(c_str!("console"), vec!(JSPropertyItem::func(c_str!("__log"),Some(c_log),1),
                                                     JSPropertyItem::func(c_str!("__error"),Some(c_error),1),
                                                     JSPropertyItem::func(c_str!("__warn"),Some(c_warn),1)
                                                    ), (q::JS_PROP_CONFIGURABLE | q::JS_PROP_WRITABLE) as u8),
      JSPropertyItem::func(c_str!("__require"),Some(c_require), 1)
            
   );
  let global = ctx.get_global_object();
  ctx.set_property_function_list(global.inner().0, &propslist);  
}

pub extern "C" fn c_log( ctx: *mut q::JSContext, _: q::JSValue, _: ::std::os::raw::c_int, 
                              argv: *mut q::JSValue) -> q::JSValue {
       unsafe { 
          let val = RawJsValue::deserialize_value(*argv, ctx).unwrap();
          println!("{}",val.to_string()); 
       } 
       RawJsValue::val_null()
}

pub extern "C" fn c_error( ctx: *mut q::JSContext,_: q::JSValue,_: ::std::os::raw::c_int, 
                                argv: *mut q::JSValue) -> q::JSValue {
       unsafe { 
          let val = RawJsValue::deserialize_value(*argv, ctx).unwrap();
          eprintln!("{}",Red.paint(val.to_string())); 
       } 
       RawJsValue::val_null()
}

pub extern "C" fn c_warn( ctx: *mut q::JSContext,_: q::JSValue,_: ::std::os::raw::c_int, 
                               argv: *mut q::JSValue) -> q::JSValue {
       unsafe { 
          let val = RawJsValue::deserialize_value(*argv, ctx).unwrap();
          eprintln!("{}",Yellow.paint(val.to_string())); 
       } 
       RawJsValue::val_null()
}


pub unsafe extern "C" fn c_require(ctx: *mut q::JSContext,_: q::JSValue,count:std::os::raw::c_int,argv: *mut q::JSValue) -> q::JSValue {
   let args = std::slice::from_raw_parts(argv, count as usize);
   let m_path = RawJsValue::deserialize_value(args[0],ctx).unwrap().to_string();
   let c_path = CString::new(m_path.as_str()).unwrap();
   //println!("r_require:{:?}",m_path);
   let ptr = std::mem::transmute(c_path.as_ptr());
 
   let ret = q::JS_Require(ctx,ptr,args[1]);
   let raw_ret = RawJsValue(ret);
   if raw_ret.is_exception() {
      let _err_str = JSContext::get_exception_raw(ctx);
      eprintln!("{:?}",_err_str.unwrap());
      return RawJsValue::val_exception();
   }
   //println!("r_require:{:?}",m_path);
   return ret;
}



